package com.lsh.oms.provider.service.aspect;

import com.alibaba.fastjson.JSONObject;
import com.lsh.base.common.model.CommonResult;
import com.lsh.oms.api.model.status.CancelOrderDto;
import com.lsh.oms.core.constant.ReturnCode;
import com.lsh.oms.core.enums.*;
import com.lsh.oms.core.model.order.OrderHead;
import com.lsh.oms.core.model.payment.BillPaymentInfo;
import com.lsh.oms.core.model.po.OmsTask;
import com.lsh.oms.core.service.order.OrderQueryService;
import com.lsh.oms.core.service.payment.BillPaymentService;
import com.lsh.oms.core.service.po.OmsTaskService;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.List;

/**
 * Project Name: RefundAop
 * 北京链商电子商务有限公司
 * Auth: wangliutao
 * Date: 18/6/6
 * Package Name: com.lsh.oms.provider.service.aspect
 * Description:业务场景:
 *    用户下单,且是在线已支付;当用户取消、客服取消、mis取消等订单取消时,需要发起用户退款!
 *    退款申请由定时任务触发,向商城发起退款
 */
@Aspect
@Component
public class OrderCancelAop {
    private static final Logger logger = LoggerFactory.getLogger(OrderCancelAop.class);

    private static final String CANCEL_TYPE = "type";
    @Autowired
    private OrderQueryService orderQueryService;

    @Autowired
    private OmsTaskService omsTaskService;

    @Autowired
    private BillPaymentService billPaymentService;

    /**
     * 切入点表达式
     */
    @Pointcut("execution(* com.lsh.oms.provider.service.status.OrderCancelServiceImpl.cancelOrder*(..)) " +
//            "|| execution(* com.lsh.oms.provider.service.order.OrderCreateRestServiceImpl.cancel(..)) " +
            "|| execution(* com.lsh.oms.core.service.order.OrderCancelService.orderAllPickUpShortCancel(..))")
    private void expression() {
    }

    @AfterReturning(returning = "obj", pointcut = "expression()")
    public void logAround(JoinPoint joinPoint, Object obj) {
        Object[] args = joinPoint.getArgs();
        logger.info("[预付--退款] simple class name: {}, method name: {}", joinPoint.getSignature().getDeclaringType().getSimpleName(), joinPoint.getSignature().getName());
        logger.info("[预付--退款] target method args: {}", args);
        boolean skipValidation = false;
        JSONObject ext = new JSONObject();
        Long orderCode = null;
        for (Object arg : args) {
            if (arg instanceof CancelOrderDto) {
                CancelOrderDto cancelOrderDto = (CancelOrderDto) arg;
                orderCode = cancelOrderDto.getOrderCode();
                break;
            }
            if (arg instanceof Long) {
                orderCode = (Long) arg;
                skipValidation = true;
                ext.put(CANCEL_TYPE, OrderRefundTypeEnum.ORDER_CANCEL_CUSTOMERSERVICE.getValue());
                ext.put("coupon", true);
                break;
            }
        }

        if (orderCode == null) {
            return;
        }

        if (obj instanceof CommonResult) {
            CommonResult commonResult = (CommonResult) obj;
            if (ReturnCode.REQUEST_SUCCESS.equals(commonResult.getCode()) || CommonResult.SUCCESS.equals(commonResult.getCode())) {
                try {

                    this.couponDeal2addOmsTask(orderCode);
                    this.refundAndInsertOmsTask(skipValidation, orderCode, ext);
                } catch (Exception e) {
                    logger.info("[预付--退款] insert oms task failed! orderCode: {}", orderCode);
                    logger.error("[预付--退款] insert oms task error! msg: " + e.getMessage(), e);
                }
            }
        }

    }

    /**
     *
     * @param orderCode
     */
    private void couponDeal2addOmsTask(Long orderCode){
        OrderHead orderHead = orderQueryService.findByCode(orderCode, false, false);
        if (orderHead == null) {
            logger.info("[订单完成] 查询不到orderHead记录, orderCode: {}", orderCode);
            return;
        }

        OmsTask filter = new OmsTask();
        filter.setRefCode(orderCode.toString());
        filter.setTaskType(TaskType.ORDER_COUPON.getCode());
        List<OmsTask> tasks = omsTaskService.getTasksByFilter(filter);

        if(!CollectionUtils.isEmpty(tasks)){
            return;
        }

        OmsTask task = new OmsTask();
        task.setRefCode(orderCode.toString());
        task.setTaskType(TaskType.ORDER_COUPON.getCode());
        task.setContent(orderCode.toString());
        task.setTaskStatus(TaskStatus.TASK_UN_DEAL.getCode());
        task.setVenderId(orderHead.getVenderId());
        logger.info("[订单完成] insert oms task start! orderCode: {}", orderCode);
        omsTaskService.add(task);
        logger.info("[订单完成] insert oms task end! orderCode: {}", orderCode);
    }

    /**
     *
     * @param skipValidation
     * @param orderCode
     * @param ext
     */
    private void refundAndInsertOmsTask(boolean skipValidation, Long orderCode, JSONObject ext) {
        OrderHead orderHead = orderQueryService.findByCode(orderCode, false, false);
        if (orderHead == null) {
            logger.info("[预付--退款] 查询不到orderHead记录, orderCode: {}", orderCode);
            return;
        }

        // 如果是全单捡缺，不管支付类型，都需要通知商城退券
        if (!skipValidation) {
            if (PayType.PAY_ON_DELIVERY.getValue().equals(orderHead.getPayType())) {
                logger.info("[预付--退款] 订单支付类型, payType: {}, orderCode: {}", PayType.getName(orderHead.getPayType()), orderCode);
                return;
            }
            if (!PayStatus.PAID.getValue().equals(orderHead.getPayStatus())) {
                logger.info("[预付--退款] 订单支付状态, payStatus: {}, orderCode: {}", PayStatus.getName(orderHead.getPayStatus()), orderCode);
                BillPaymentInfo payFilter = new BillPaymentInfo();
                payFilter.setBillCode(orderCode);
                payFilter.setPayStatus(PayStatus.PAID.getValue());
                payFilter.setIsValid(1);
                Integer count = billPaymentService.countByFilter(payFilter);
                if (count == null || count.intValue() == 0) {
                    logger.info("[预付--退款] 订单没有支付成功的记录, orderCode: {}", orderCode);
                    return;
                }
            }
        }

        // 如果omsTask中,已经有该订单的退款记录,则不再插入(防止目标方法,做了幂等,导致的重复插入omsTask的情况发生)
        OmsTask filter = new OmsTask();
        filter.setRefCode(orderCode.toString());
        filter.setTaskType(TaskType.REFUND.getCode());
        List<OmsTask> tasks = omsTaskService.getTasksByFilter(filter);
        if (!CollectionUtils.isEmpty(tasks)) {
            return;
        }

        OrderStatus orderStatus = OrderStatus.indexOf(orderHead.getOrderStatus());
        if (orderStatus == null) {
            return;
        }
        logger.info("[预付--退款] 订单状态: {}", orderStatus.getName());
        if (ext.size() == 0) {
            switch (orderStatus) {
                case ORDER_CANCEL_CUSTOMERSERVICE:
                    ext.put(CANCEL_TYPE, OrderRefundTypeEnum.ORDER_CANCEL_CUSTOMERSERVICE.getValue());
                    break;
                case ORDER_CANCEL_CUSTOMER:
                    ext.put(CANCEL_TYPE, OrderRefundTypeEnum.ORDER_CANCEL_CUSTOMER.getValue());
                    break;
                default:
                    ext.put(CANCEL_TYPE, OrderRefundTypeEnum.ORDER_CANCEL_SYSTEM.getValue());
            }
        }

        OmsTask task = new OmsTask();
        task.setRefCode(orderCode.toString());
        task.setTaskType(TaskType.REFUND.getCode());
        task.setVenderId(orderHead.getVenderId());
        task.setExt(ext.toJSONString());
        logger.info("[预付--退款] insert oms task start! orderCode: {}", orderCode);
        omsTaskService.add(task);
        logger.info("[预付--退款] insert oms task end! orderCode: {}", orderCode);
    }

}